<?php
declare(strict_types=1);

namespace App\Controller;

use App\Constants\CacheKey;
use App\Constants\Consts;
use App\Libs\DingDing;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
use function Hyperf\Support\env;

/**
 * sitemap管理
 */
class SitemapController extends AbstractController
{
    #[Inject(required: true)]
    protected Redis $redis;

    public function robots(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        try {
            $post = $request->all();
            $post['group_no'] = trim($request->route('group_no', ''));
            $params = getExtendParams($post);
            mt_srand(crc32($params['domain_nohttp']));
            $xmlNum = mt_rand(Consts::XMLNUM_ROBOTS_MIN, Consts::XMLNUM_ROBOTS_MAX);
            $str = Consts::TEMPLATE_ROBOTS_1;
            $str .= sprintf(Consts::TEMPLATE_ROBOTS_2, $params['domain'] . '/sitemap.xml');
            for ($i = 1; $i <= $xmlNum; $i++) {
                $str .= sprintf(Consts::TEMPLATE_ROBOTS_2, $params['domain'] . '/sitemap-' . $i . '.xml');
            }
            if (str_contains($params['hosturl'], '.php')) {
                // 说明是二级php文件进来
                $str .= sprintf(Consts::TEMPLATE_ROBOTS_2, $params['hosturl'] . 'sitemap.xml');
                for ($i = 1; $i <= $xmlNum; $i++) {
                    $str .= sprintf(Consts::TEMPLATE_ROBOTS_2, $params['hosturl'] . 'sitemap-' . $i . '.xml');
                }
            }
            return $response->raw($str);
        } catch (\Throwable $e) {
            $msg = 'robots error,msg=' . $e->getMessage() . ',file:' . $e->getFile() . ',line:' . $e->getLine();
            logger()->error($msg);
            DingDing::sendErrorMsg($msg);
            return $response->raw('');
        }
    }

    public function beima1(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        $path = BASE_PATH . '/storage/stub/beima_tool.stub';
        $str = file_get_contents($path);
        return $response->raw($str);
    }

    public function beima2(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        $path = BASE_PATH . '/storage/stub/beima_md5.stub';
        $str = file_get_contents($path);
        return $response->raw($str);
    }

    public function map(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        try {
            $post = $request->all();
            $post['group_no'] = trim($request->route('group_no', ''));
            $params = getExtendParams($post);
            $str = Consts::TEMPLATE_SITEMAPINDEX_START;
            if (str_contains($params['uri'], 'mapindex.xml')) {
                $today = date('Y-m-d');
                $xmlArr = range(Consts::XMLNUM_MAPINDEX_MIN, Consts::XMLNUM_MAPINDEX_MAX);
                shuffle($xmlArr);
                $arr = array_slice($xmlArr, 0, Consts::XMLNUM_MAPINDEX);
                foreach ($arr as $xml) {
                    $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . 'sitemap' . $xml . '.xml', $today);
                }
            } elseif (str_contains($params['uri'], 'sitemap-index.xml')) {
                $today = date('Y-m-d');
                $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . 'sitemap' . $today . '.xml', $today);
                for ($i = 1; $i <= Consts::XMLNUM_SITEMAPMAP_INDEX; $i++) {
                    $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . 'sitemap' . date("Y-m-d", strtotime("-$i day")) . '.xml', $today);
                }
            } elseif (str_contains($params['uri'], 'sitemap-index-1.xml')) {
                $today = date('Y-m-d');
                $xmlArr = range(Consts::XMLNUM_SITEMAPMAP_INDEX_1_MIN, Consts::XMLNUM_SITEMAPMAP_INDEX_1_MAX);
                shuffle($xmlArr);
                for ($i = 0; $i < Consts::XMLNUM_SITEMAPMAP_INDEX_1; $i++) {
                    $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . 'sitemap' . $xmlArr[$i] . '.xml', $today);
                }
            } elseif (str_contains($params['uri'], 'sxallsitemap.xml')) {
                return $response->raw('ok' . '|' . env('APP_NAME'));
            } elseif (str_contains($params['uri'], 'allsitemap.xml')) {
                $allsitemapUrl = str_replace(["http://", "https://"], "", $params['url']);
                mt_srand(crc32($allsitemapUrl));
                $wordsContent = @file_get_contents(BASE_PATH . Consts::WORDS_PATH);
                $wordsArr = explode(PHP_EOL, $wordsContent);
                $wordsArr = array_filter($wordsArr);
                $wordsLen = count($wordsArr);

                for ($j = 0; $j < Consts::XMLNUM_ALLSITEMAPMAP; $j++) {
                    $xml = $wordsArr[mt_rand(0, ($wordsLen - 1))] . randomkeys(3, 1);
                    $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . $xml . '.xml');
                }
            } else {
                $wordsContent = @file_get_contents(BASE_PATH . Consts::WORDS_PATH);
                $wordsArr = explode(PHP_EOL, $wordsContent);
                $wordsArr = array_filter($wordsArr);
                $wordsLen = count($wordsArr);

                $limit = mt_rand(Consts::XMLNUM_INDEX_MIN, Consts::XMLNUM_INDEX_MAX);
                for ($i = 0; $i < $limit; $i++) {
                    $xml = $wordsArr[mt_rand(0, ($wordsLen - 1))] . randomkeys(3, 1);
                    $str .= sprintf(Consts::TEMPLATE_SITEMAPINDEX_2, $params['hosturl'] . $xml . '.xml');
                }
            }
            return $response->raw($str . Consts::TEMPLATE_SITEMAPINDEX_END);
        } catch (\Throwable $e) {
            $msg = 'map error,msg=' . $e->getMessage() . ',file:' . $e->getFile() . ',line:' . $e->getLine();
            logger()->error($msg);
            DingDing::sendErrorMsg($msg);
            return $response->raw('');
        }
    }

    public function word(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        try {
            $post = $request->all();
            $post['group_no'] = trim($request->route('group_no', ''));
            $params = getExtendParams($post);
            $word = getXmlName($params['uri']);
            $allsitemapUrl = str_replace($word, "allsitemap", $params['url']);
            $allsitemapUrl = str_replace(["http://", "https://"], "", $allsitemapUrl);
            mt_srand(crc32($allsitemapUrl));

            $wordsContent = @file_get_contents(BASE_PATH . Consts::WORDS_PATH);
            $wordsArr = explode(PHP_EOL, $wordsContent);
            $wordsArr = array_filter($wordsArr);
            $wordsLen = count($wordsArr);
            $arr = [];
            for ($j = 0; $j < Consts::XMLNUM_ALLSITEMAPMAP; $j++) {
                $arr[] = $wordsArr[mt_rand(0, ($wordsLen - 1))] . randomkeys(3, 1);
            }
            if (in_array($word, $arr)) {
                // allsitemap.xml中出现的xml名称，则请求生成sitemapindex的站点地图
                return $response->raw('1');
            } else {
                mt_srand(crc32($params['domain_nowww']));
                $zhongzi = mt_rand(1000000, 4000000);
                $zimu = chr(mt_rand(65, 90));
                $shuzi = mt_rand(10, 99);

                // 因为被种种子了，这边要释放掉
                mt_srand();

                $productMaxId = $this->getProductMaxId();
                $str = Consts::TEMPLATE_URLSET_START;
                $today = date('Y-m-d');
                for ($i = 0; $i < Consts::XMLNUM_RAND; $i++) {
                    $lpid = mt_rand(1, $productMaxId);
                    $lpid = $lpid + $zhongzi;
                    $loc = $params['hosturl'] . 'detail/' . $zimu . $shuzi . $lpid;
                    $str .= sprintf(Consts::TEMPLATE_URLSET_1, $loc, $today);
                }
                return $response->raw($str . Consts::TEMPLATE_URLSET_END);
            }
        } catch (\Throwable $e) {
            $msg = 'word error,msg=' . $e->getMessage() . ',file:' . $e->getFile() . ',line:' . $e->getLine();
            logger()->error($msg);
            DingDing::sendErrorMsg($msg);
            return $response->raw('');
        }
    }

    public function jump(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
    {
        try {
            $post = $request->all();
            $post['group_no'] = trim($request->route('group_no', ''));
            $params = getExtendParams($post);
            $productMaxId = $this->getProductMaxId();

            mt_srand(crc32($params['domain_nowww']));
            $zhongzi = mt_rand(1000000, 4000000);
            mt_srand();

            $productId = getProductId($params['url_nowww'], $productMaxId, $zhongzi);
            $product = getProductContent($productId, intval(env('PRODUCTDIR_NUM')));
            $gno = env('APP_NAME');
            $str = '';
            if (!empty($product)) {
                $domain = $product[0] ?? '';
                if (!empty($domain)) {
                    $table = Consts::TABLE_JUMPDOMAIN;
                    $res = Db::select("select id,old_domain,new_domain from {$table} where old_domain='" . $domain . "' order by id desc limit 1");
                    if (!empty($res)) {
                        $domain = $res[0]->new_domain;
                    }
                }
                $productTitle = $product[12] ?? '';
                $productId = intval($product[1] ?? 0);
                $productDb = strtoupper($product[2] ?? '');

                // 落地前统计的JS
                $matomoJs = <<<JS
<script>
    var _paq = window._paq = window._paq || [];
    _paq.push(['setCustomDimension', {{APP_DIMENSION_ID1}}, '{{PRODUCT_DB}}']);
    _paq.push(['setCustomDimension', {{APP_DIMENSION_ID2}}, '{{HTTP_DOMAIN}}']);
    _paq.push(['trackPageView']);
    _paq.push(['enableLinkTracking']);
    (function() {
        var u="//{{APP_MOTOMO_URL}}/";
        _paq.push(['setTrackerUrl', u+'matomo.php']);
        _paq.push(['setSiteId', '{{APP_SITE_ID}}']);
        var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
        g.async=true; g.src=u+'matomo.js';
        g.onerror = function(){ console.error('Matomo script load error') };
        s.parentNode.insertBefore(g,s);
    })();
</script>
JS;
                $matomoJs = str_replace(
                    ['{{APP_DIMENSION_ID1}}', '{{APP_DIMENSION_ID2}}', '{{PRODUCT_DB}}', '{{HTTP_DOMAIN}}', '{{APP_MOTOMO_URL}}', '{{APP_SITE_ID}}'],
                    [env('APP_DIMENSION_ID1', 1), env('APP_DIMENSION_ID2', 2), $productDb, $params['domain_nowww'], trim(env('APP_MOTOMO_URL'), '/'), env('APP_SITE_ID')],
                    $matomoJs
                );

                // 跳转链接(落地前看pdb-即产品库统计，落地后看gno-即组号统计)
                $href = "https://{$domain}/index.php?main_page=product_info&products_id={$productId}&pdb={$productDb}&gno={$gno}";

                $str = '<!DOCTYPE html><html lang="ja"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>';
                $str .= '<title>' . $productTitle . '</title>';
                $str .= $matomoJs;
                $str .= '</head><body>';
                $str .= '<script>window.location.href="' . $href . '";</script>';
                $str .= '</body></html>';

                // 向远程保存跳转数据
                $commitData = [
                    'gno' => env('APP_NAME'),
                    'domain' => $params['domain_nowww'],
                    'requrl' => $params['url'],
                    'ip' => getRealIp(),
                    'jump_pid' => $productId,
                    'jump_domain' => $domain
                ];
                @saveJumpData2Remote(env('JUMPURL'), $commitData);
            }
            return $response->raw($str);
        } catch (\Throwable $e) {
            $msg = 'jump error,msg=' . $e->getMessage() . ',file:' . $e->getFile() . ',line:' . $e->getLine();
            logger()->error($msg);
            DingDing::sendErrorMsg($msg);
            return $response->raw('');
        }
    }

    /**
     * 获取最大ID
     */
    private function getProductMaxId()
    {
        $productMaxId = env('PRODUCT_MAXID', 0);
        if (empty($productMaxId)) {
            $productMaxId = $this->redis->get(CacheKey::PRODUCT_MAXID);
            if (!$productMaxId) {
                $productMaxId = @file_get_contents(BASE_PATH . Consts::PRODUCT_COUNT_PATH);
            }
        }
        return intval($productMaxId);
    }
}